package demo.db.tsdb;

import org.HdrHistogram.ConcurrentHistogram;
import org.HdrHistogram.Histogram;
import org.HdrHistogram.Recorder;
import org.junit.Test;

import java.nio.ByteBuffer;
import java.util.stream.IntStream;

/**
 * HdrHistogram是一个高动态范围(High Dynamic Range)的直方图统计工具。它能够以高精度记录数值分布，特别适合记录延迟等指标的分布情况。
 * <p>
 * 主要特点：
 * <li>高精度：支持任意精度的数值记录；可配置有效数字精度；零内存分配操作
 * <li>低开销：记录操作的延迟很低；内存占用可预测；支持并发环境使用
 * <li>主要应用场景：延迟统计；响应时间分析；性能测试；系统监控
 * <p>
 * 最佳实践：
 *
 * <li>选择合适的精度：一般3-4位有效数字够用，精度越高内存占用越大
 * <li>合理设置值范围：根据实际场景设置最大最小值，避免过大范围导致内存浪费
 * <li>定期重置：长期运行时注意定期重置，保持统计数据的时效性
 * <li>并发场景： 使用ConcurrentHistogram，注意线程安全
 * <li>监控集成：与监控系统集成，设置合理的告警阈值
 */
public class HdrHistogramDemo {


    /**
     * 基本使用示例
     */
    @Test
    public void testHistogram() {
        // 1. 创建Histogram实例
        Histogram histogram = new Histogram(3); // 3表示有效数字精度

        // 2. 记录数据
        IntStream.range(0, 300).forEach(histogram::recordValue);

        // 3. 获取统计信息
        // 获取最大值
        long max = histogram.getMaxValue();
        // 获取最小值
        long min = histogram.getMinValue();
        // 获取平均值
        double mean = histogram.getMean();
        // 获取标准差
        double stdDeviation = histogram.getStdDeviation();
        // 获取总计数
        long totalCount = histogram.getTotalCount();
        // 获取某个百分位的值
        double p99 = histogram.getValueAtPercentile(99.0);
        double p999 = histogram.getValueAtPercentile(999.0);
        System.out.println("max=" + max + ",min=" + min + ",平均值=" + mean + ",标准差=" + stdDeviation + ",totalCount=" + totalCount + ",p99=" + p99 + ",p999=" + p999);
        // 4. 重置直方图
        histogram.reset();
    }

    @Test
    public void test2() {
        // 1. 创建带值范围的Histogram
        Histogram histogram = new Histogram(1, 3600000L, 3); // 1ms到1小时范围

        // 2. 使用记录器模式
        Recorder recorder = new Recorder(3);
        recorder.recordValue(100);
        // 获取并重置当前记录
        Histogram current = recorder.getIntervalHistogram();


        // 3. 并发记录
        ConcurrentHistogram concurrentHistogram = new ConcurrentHistogram(3);
        // 多线程安全记录
        concurrentHistogram.recordValue(100);

        // 4. 累积直方图
        Histogram accumulatedHistogram = new Histogram(3);
        // 合并其他直方图数据
        accumulatedHistogram.add(histogram);

        // 5. 编码/解码
        ByteBuffer buffer = ByteBuffer.allocate(histogram.getNeededByteBufferCapacity());
        histogram.encodeIntoByteBuffer(buffer);
        // 从buffer解码
        Histogram newHistogram = Histogram.decodeFromByteBuffer(buffer, 0);

    }

    /**
     * Recorder 类是一个用于并发记录数据的工具，它使用了双缓冲技术来实现高效的数据记录。Recorder 本身是线程安全的
     */
    @Test
    public void testRecorder() {
        Recorder recorder = new Recorder(1, 10000, 3);
        for (int i = 0; i <= 10000; i++) {
            recorder.recordValue(i);
            if (i >= 1000 && i % 1000 == 0) {
                // 获取并重置当前记录
                Histogram current = recorder.getIntervalHistogram();
                System.out.println("max=" + current.getMaxValue() +
                        ",min=" + current.getMinValue() +
                        ",平均值=" + current.getMean() +
                        ",标准差=" + current.getStdDeviation() +
                        ",totalCount=" + current.getTotalCount() +
                        ",p50=" + current.getValueAtPercentile(50) +
                        ",p99=" + current.getValueAtPercentile(99));
            }
        }
        recorder.reset();
        Histogram current = recorder.getIntervalHistogram();
        System.err.println("max=" + current.getMaxValue() +
                ",min=" + current.getMinValue() +
                ",平均值=" + current.getMean() +
                ",标准差=" + current.getStdDeviation() +
                ",totalCount=" + current.getTotalCount() +
                ",p50=" + current.getValueAtPercentile(50) +
                ",p99=" + current.getValueAtPercentile(99));
    }

    /**
     * Recorder 类是一个用于并发记录数据的工具，它使用了双缓冲技术来实现高效的数据记录。Recorder 本身是线程安全的
     */
    @Test
    public void testConcurrentHistogram() {
        ConcurrentHistogram histogram = new ConcurrentHistogram(1, 10000, 3);
        for (int i = 0; i <= 20000; i++) {
            try {
                histogram.recordValue(i);
            } catch (ArrayIndexOutOfBoundsException e) {
                e.printStackTrace();
                throw e;
            }
            if (i >= 1000 && i % 1000 == 0) {
                // 获取并重置当前记录
                System.out.println("max=" + histogram.getMaxValue() +
                        ",min=" + histogram.getMinValue() +
                        ",平均值=" + histogram.getMean() +
                        ",标准差=" + histogram.getStdDeviation() +
                        ",totalCount=" + histogram.getTotalCount() +
                        ",p50=" + histogram.getValueAtPercentile(50) +
                        ",p99=" + histogram.getValueAtPercentile(99));
                histogram.reset();
            }
        }
    }


}
